﻿unit sFRHandle;

interface

uses
  sReportHandle, Classes, DB, Controls, frxClass, frxDesgn, Printers,IniFiles,
  Grids, DBGrids, frxDBSet, frxCross, frxExportPDF, sReportSetting, frxUtils,
  frxPrinter, frxPreviewPageSettings, frxExportImage, frxExportXLS, frxExportHTML,
  DBGridEh;
  


type

  TFRSetting = class(TReportSettingHandle)
  public
    procedure LoadSetting; override;
  end;


  TFRHandle = class(TPrintReportHandle)
  private
    FFRSetting: TFRSetting;

    FDataGrid: TCustomControl;

    FfrxDataSet: TfrxDBDataSet;
    FfrxPDFExport: TfrxPDFExport;
    FfrxXLSExport: TfrxXLSExport;
    FfrxBmpExport: TfrxBMPExport;
    FfrxHTMLExport: TfrxHTMLExport;
    
    FFastRep: TfrxReport;

    FPage: TfrxReportPage;
    FDataPage: TfrxDataPage;
    FTitleBand: TfrxReportTitle;
    FPageHeader: TfrxPageHeader;
    //FHeader: TfrxHeader;
    FMasterData: TfrxMasterData;
    //FDetailData: TfrxDetailData;
    FFooter: TfrxFooter;
    FPageFooter: TfrxPageFooter;


    FRepColumns: TRepColumnCollection;

    function GetFastRep: TfrxReport;
  protected
    procedure OnReportBeforePrint(c: TfrxReportComponent);

    function GetDataset: TDataSet; override;
    procedure SetDataset(const Value: TDataSet); override;

    function GetDataGrid: TCustomControl; override;
    procedure SetDataGrid(const Value: TCustomControl); override;

    procedure IniParam; override;

    procedure BuildReport;

    procedure BuildBand;
    procedure BuildTitle;
    procedure BuildPageHeader;
    procedure BuildMasterData;
    procedure BuildDetailData;
    procedure BuildFooter;
    procedure BuildPageFooter;

    procedure FillFieldData;

  public
    constructor Create();
    destructor Destroy; override;

    //直接打印
    procedure Print; override;
    //预览打印
    procedure Preview; override;
    //设计报表
    procedure Design; override;
    //报表设置
    procedure ReportSetting; override;

    property FastRep: TfrxReport read GetFastRep;
  end;





implementation

function UnitsTomm(mm: Extended): Extended;
begin
  Result := mm * 10;
end;


{ TFRPrintHandle }

procedure TFRHandle.BuildBand;
begin
  FFastRep.Clear;
  { add a dataset to the list of ones accessible for a report }
  FFastRep.DataSets.Add(FfrxDataSet);
  { add the "Data" FPage }
  FDataPage := TfrxDataPage.Create(FFastRep);
  { add a FPage }
  FPage := TfrxReportPage.Create(FFastRep);
  { create a unique name }
  FPage.CreateUniqueName;
  { set sizes of fields, paper and orientation by default }
  FPage.SetDefaults;


  with FFRSetting do
  begin
    case Orientation of
      Report_Portrait: FPage.Orientation := poPortrait;
      Report_Landscape: FPage.Orientation := poLandscape;
      else
        FPage.Orientation := poPortrait;
    end;


    FPage.PaperWidth := UnitsTomm(frxStrToFloat(PaperWidth));
    FPage.PaperHeight := UnitsTomm(frxStrToFloat(PaperHeight));
    FPage.PaperSize := frxPrinters.Printer.PaperNameToNumber(PaperSize);

    FPage.LeftMargin := UnitsTomm(frxStrToFloat(LeftMargin));
    FPage.RightMargin := UnitsTomm(frxStrToFloat(RightMargin));
    FPage.TopMargin := UnitsTomm(frxStrToFloat(TopMargin));
    FPage.BottomMargin := UnitsTomm(frxStrToFloat(BottomMargin));

    FPage.AlignChildren;
  end;


  { add a report title band}
  FTitleBand := TfrxReportTitle.Create(FPage);
  with FTitleBand do
  begin
    CreateUniqueName;
    Top := 0;
    Height := 60;
    Width := FPage.Width;
  end;



  FPageHeader := TfrxPageHeader.Create(FPage);
  with FPageHeader do
  begin
    CreateUniqueName;
    Top := 50;
    Height := 30;
    Width := FPage.Width;
  end;

  FMasterData := TfrxMasterData.Create(FPage);
  FMasterData.DataSet := FfrxDataSet;
  with FMasterData do
  begin
    CreateUniqueName;
    Top := 90;
    Height := 20;
    Width := FPage.Width;
    Stretched := True;
  end;


  FFooter := TfrxFooter.Create(FPage);
  with FFooter do
  begin
    CreateUniqueName;
    Top := 130;
    Height := 30;
    Width := FPage.Width;
  end;

  FPageFooter := TfrxPageFooter.Create(FPage);
  with FPageFooter do
  begin
    CreateUniqueName;
    Top := 170;
    Height := 30;
    Width := FPage.Width;
  end;

end;

procedure TFRHandle.BuildMasterData;
var
  afrxMemo: TfrxMemoView;
  i: Integer;
begin
  for i := 0 to FRepColumns.Count - 1 do
  begin
    afrxMemo := TfrxMemoView.Create(FMasterData);
    with afrxMemo do
    begin
      Top := 0;
      Left := FRepColumns.Items[i].Left;
      Width := FRepColumns.Items[i].Width;
      Text := FRepColumns.Items[i].Caption;
      Height := FMasterData.Height;
      VAlign := vaCenter;
      HAlign := haCenter;
      DataSet := FfrxDataSet;
      DataField := FRepColumns.Items[i].DBField;
      Frame.Typ := [ftLeft, ftRight, ftTop, ftBottom];
      StretchMode := smMaxHeight;
    end;
  end;
end;

procedure TFRHandle.BuildDetailData;
begin


end;


procedure TFRHandle.BuildFooter;
begin
  with TfrxMemoView.Create(FFooter) do
  begin
    CreateUniqueName;
    Text := '制表人：         审核：            打印日期 [Date] [Time]';
    Height := 20;
    Align := baClient;
    Width := 500;
    VAlign := vaCenter;
    HAlign := haRight;
  end;
end;

procedure TFRHandle.BuildPageHeader;
var
  Memo: TfrxMemoView;
  i: Integer;
begin
  for i := 0 to FRepColumns.Count - 1 do
  begin
    Memo := TfrxMemoView.Create(FPageHeader);
    with Memo do
    begin
      Top := 0;
      Left := FRepColumns.Items[i].Left;
      Width := FRepColumns.Items[i].Width;
      Text := FRepColumns.Items[i].Caption;
      Height := FPageHeader.Height;
      VAlign := vaCenter;
      HAlign := haCenter;
      Frame.Typ := [ftLeft, ftRight, ftTop, ftBottom];
      Color := $00F0F0F0;
    end;
  end;
end;

procedure TFRHandle.BuildPageFooter;
begin
  with TfrxMemoView.Create(FPageFooter) do
  begin
    CreateUniqueName;
    Text := ' [Page#] of [TotalPages#] ';
    Height := 20;
    Align := baClient;
    VAlign := vaCenter;
    HAlign := haCenter;
    Frame.Typ := [ftTop];
    Frame.Width := 1.5;
  end;
end;

procedure TFRHandle.BuildReport;
begin
  FFastRep.DataSets.Add(FfrxDataSet);
  BuildBand;
  FillFieldData;
  BuildPageHeader;
  BuildTitle;
  BuildMasterData;
  BuildDetailData;
  BuildFooter;
  BuildPageFooter;

end;

procedure TFRHandle.BuildTitle;
begin
  with TfrxMemoView.Create(FTitleBand) do
  begin
    CreateUniqueName;
    Text := Title;
    Height := 20;
    Align := baClient;
    VAlign := vaCenter;
    HAlign := haCenter;
    Font.Name := '宋体';
    Font.Size := 16;
  end;
end;

constructor TFRHandle.Create;
begin
  inherited;
  FRepColumns := TRepColumnCollection.Create;
  
  FFastRep := TfrxReport.Create(nil);
  
  FfrxDataSet := TfrxDBDataSet.Create(nil);
  //导出
  FfrxPDFExport := TfrxPDFExport.Create(nil);
  FfrxXLSExport := TfrxXLSExport.Create(nil);
  FfrxBmpExport := TfrxBMPExport.Create(nil);
  FfrxHTMLExport := TfrxHTMLExport.Create(nil);

  
  FFastRep.OnBeforePrint := OnReportBeforePrint;

  FFRSetting := TFRSetting.Create('');
  FFRSetting.LoadSetting;
end;


procedure TFRHandle.Design;
begin
  inherited;
  BuildReport;
  FastRep.DesignReport;

end;

destructor TFRHandle.Destroy;
begin
  FRepColumns.Free;
  FFastRep.Free;
  FfrxDataSet.Free;
  FfrxPDFExport.Free;
  FfrxXLSExport.Free;
  FfrxBmpExport.Free;
  FfrxHTMLExport.Free;
  
  inherited;
end;


procedure TFRHandle.FillFieldData;
var
  i: integer;
  baseWidth, bankWidth: Integer;

  procedure FillDBGrid(aGrid: TDBGrid);
  var
    i: integer;
  begin
    FRepColumns.TotalWidth := 0;
    for i := 0 to aGrid.Columns.Count - 1 do
    begin
      if aGrid.Columns[i].Visible then
      begin
        FRepColumns.TotalWidth := FRepColumns.TotalWidth + aGrid.Columns[i].Width;
        with FRepColumns.Add do
        begin
          Width := aGrid.Columns[i].Width;
          //每个字段框在报表中的left
          //Left := ;
          //字段名
          DBField := aGrid.Columns[i].FieldName;
          //标题
          Caption := aGrid.Columns[i].Title.Caption;
          //对齐
          Alignment := taCenter;
          //是否可见
          Visible := aGrid.Columns[i].Visible;
        end;
      end;
    end;
  end;

  procedure FillStrGrid(aGrid: TStringGrid);
  var
    i: integer;
  begin
    FRepColumns.TotalWidth := 0;
    for i := 0 to aGrid.ColCount - 1 do
    begin
      FRepColumns.TotalWidth := FRepColumns.TotalWidth + aGrid.ColWidths[i];
      with FRepColumns.Add do
      begin
        Width := aGrid.ColWidths[i];
        //每个字段框在报表中的left
        //Left := ;
        //字段名
        //DBField := aGrid.Columns[i].FieldName;
        //标题
        Caption := aGrid.Cells[i, 0];
        //对齐
        Alignment := taCenter;
        //是否可见
        Visible := True;
      end;
    end;
  end;

  procedure FillDBGridEh(aGrid: TDBGridEH);
  var
    i: integer;
  begin
    FRepColumns.TotalWidth := 0;
    for i := 0 to aGrid.Columns.Count - 1 do
    begin
      if aGrid.Columns[i].Visible then
      begin
        FRepColumns.TotalWidth := FRepColumns.TotalWidth + aGrid.Columns[i].Width;
        with FRepColumns.Add do
        begin
          Width := aGrid.Columns[i].Width;
          //每个字段框在报表中的left
          //Left := ;
          //字段名
          DBField := aGrid.Columns[i].FieldName;
          //标题
          Caption := aGrid.Columns[i].Title.Caption;
          //对齐
          Alignment := taCenter;
          //是否可见
          Visible := aGrid.Columns[i].Visible;
        end;
      end;
    end;
  end;



begin
  FRepColumns.Clear;

  if not Assigned(FDataGrid) then
  begin
    FRepColumns.TotalWidth := 0;
    for i := 0 to DataSet.FieldCount - 1 do
    begin
      with FRepColumns.Add do
      begin
        Width := 1;
        //每个字段框在报表中的left
        //Left := ;
        //字段名
        //DBField := aGrid.Columns[i].FieldName;
        //标题
        Caption := DataSet.Fields[i].FieldName;
        //对齐
        Alignment := taCenter;
        //是否可见
        Visible := True;
      end;
    end;

  end
  else
  begin

    if FDataGrid is TDBGrid then
    begin
      FillDBGrid(FDataGrid as TDBGrid);
    end
    else if FDataGrid is TStringGrid then
    begin
      FillStrGrid(FDataGrid as TStringGrid);
    end
    else if FDataGrid is TDBGridEH then
    begin
      FillDBGridEH(FDataGrid as TDBGridEH);
    end


  end;

  //bankWidth := Trunc(FPage.Width - FPage.LeftMargin - FPage.RightMargin);
  //这个很晕人！！
  bankWidth := Trunc(FPage.Width * (FPage.PaperWidth - FPage.LeftMargin -
    FPage.RightMargin) / FPage.PaperWidth);

  baseWidth := 0;

  for i := 0 to FRepColumns.Count - 1 do
  begin
    FRepColumns.Items[i].Left := baseWidth;

    FRepColumns.Items[i].Width := Trunc(bankWidth *
      (FRepColumns.Items[i].Width / FRepColumns.TotalWidth));

    baseWidth := baseWidth + FRepColumns.Items[i].Width;
  end;

  if FRepColumns.Count > 1 then
  begin
    FRepColumns.Items[FRepColumns.Count-1].Width := Trunc(bankWidth -
      (FRepColumns.Items[FRepColumns.Count-2].Left +
      FRepColumns.Items[FRepColumns.Count-2].Width));

  end;
  FRepColumns.TotalWidth := bankWidth;

end;

function TFRHandle.GetDataGrid: TCustomControl;
begin
  Result := FDataGrid;
end;

function TFRHandle.GetDataset: TDataSet;
begin
  if Assigned(FfrxDataSet) then
    Result := FfrxDataSet.DataSet
  else
    Result := nil;
end;

function TFRHandle.GetFastRep: TfrxReport;
begin
  Result := FFastRep;
end;

procedure TFRHandle.IniParam;
begin
  inherited;

end;

procedure TFRHandle.OnReportBeforePrint(c: TfrxReportComponent);
var
  Cross: TfrxCrossView;
  i, j: Integer;
begin
  if c is TfrxCrossView then
  begin
    Cross := TfrxCrossView(c);

    DataSet.First;
    i := 0;
    while not DataSet.Eof do
    begin
      for j := 0 to DataSet.Fields.Count - 1 do
        Cross.AddValue([i], [DataSet.Fields[j].DisplayLabel], [DataSet.Fields[j].AsString]);

      DataSet.Next;
      Inc(i);
    end;
  end;
end;

procedure TFRHandle.Preview;
begin
  inherited;
  BuildReport;
  FastRep.ShowReport;

end;

procedure TFRHandle.Print;
begin
  inherited;
  BuildReport;
  FastRep.Print;
end;


procedure TFRHandle.SetDataGrid(const Value: TCustomControl);
begin
  inherited;
  FDataGrid := Value;
end;

procedure TFRHandle.SetDataset(const Value: TDataSet);
begin
  inherited;
  FfrxDataSet.DataSet := Value;
end;


procedure TFRHandle.ReportSetting;
begin
  BuildBand;

  with TfrxPageSettingsForm.Create(nil) do
  begin
    try
      Page := FPage;
      Report := FastRep;
      if ShowModal = mrOk then
      begin
        if PortraitRB.Checked then
          Page.Orientation := poPortrait else
          Page.Orientation := poLandscape;

        Page.PaperWidth := UnitsTomm(frxStrToFloat(WidthE.Text));
        Page.PaperHeight := UnitsTomm(frxStrToFloat(HeightE.Text));
        Page.PaperSize := frxPrinters.Printer.PaperNameToNumber(SizeCB.Text);

        Page.LeftMargin := UnitsTomm(frxStrToFloat(MarginLeftE.Text));
        Page.RightMargin := UnitsTomm(frxStrToFloat(MarginRightE.Text));
        Page.TopMargin := UnitsTomm(frxStrToFloat(MarginTopE.Text));
        Page.BottomMargin := UnitsTomm(frxStrToFloat(MarginBottomE.Text));

        Page.AlignChildren;

        with FFRSetting do
        begin
          case FPage.Orientation of
            poPortrait: Orientation := Report_Portrait;
            poLandscape: Orientation := Report_Landscape;
            else
              Orientation := Report_Portrait;
          end;

          PaperWidth := WidthE.Text;
          PaperHeight := HeightE.Text;
          PaperSize := SizeCB.Text;

          LeftMargin := MarginLeftE.Text;
          RightMargin := MarginRightE.Text;
          TopMargin := MarginTopE.Text;
          BottomMargin := MarginBottomE.Text;

          FFRSetting.SaveSetting;
        end; 
      end;      
    finally
      Free;
    end;
  end;

end;

{ TFRSetting }

procedure TFRSetting.LoadSetting;
var
  aOri: Integer;
  aIni: TIniFile;
begin
  aIni := TIniFile.Create(FIniFileName);
  try
     aOri  := aIni.ReadInteger(C_ReportSettingSection, 'Orientation', 0);
     if not (aOri in [0,1]) then
     begin
       Orientation := Report_Portrait;
     end
     else
     begin
       Orientation := TReportOrientation(aOri);
     end;


     PaperWidth   := aIni.ReadString(C_ReportSettingSection, 'PaperWidth', '21');
     PaperHeight  := aIni.ReadString(C_ReportSettingSection, 'PaperHeight', '29.70');
     PaperSize    := aIni.ReadString(C_ReportSettingSection, 'PaperSize', 'A4');

     LeftMargin   := aIni.ReadString(C_ReportSettingSection, 'LeftMargin', '1');
     RightMargin  := aIni.ReadString(C_ReportSettingSection, 'RightMargin', '1');
     TopMargin    := aIni.ReadString(C_ReportSettingSection, 'TopMargin', '1');
     BottomMargin := aIni.ReadString(C_ReportSettingSection, 'BottomMargin', '1');

  finally
    aIni.Free;
  end;
end;

end.
